package com.CST.service.impl.ys;

import com.CST.common.constant.Constants;
import com.CST.dto.ys.YsCollectionRecordDTO;
import com.CST.entity.ys.*;
import com.CST.mapper.cst.ys.YsEtlAccountMapper;
import com.CST.mapper.cst.ys.YsSubjectMapper;
import com.CST.mapper.ecology.CollectionAssetMapper;
import com.CST.mapper.ufdata.CollectionAccountMapper;
import com.CST.service.ys.YsEtlAccountService;
import com.CST.util.HttpUtil;
import com.CST.util.PageHelperTool;
import com.CST.util.ThreadPoolProxy;
import com.CST.vo.ys.YsDeptVO;
import com.CST.vo.ys.YsSubjectListVO;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationTargetException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.CST.common.method.CommonMethod.getFirstDay;
import static com.CST.common.method.CommonMethod.getLastDay;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author qtx
 * @since 2023-04-20
 */
@Service
public class YsEtlAccountServiceImpl extends ServiceImpl<YsEtlAccountMapper, YsEtlAccount> implements YsEtlAccountService {

    @Autowired
    private CollectionAccountMapper collectionAccountMapper;

    @Autowired
    private CollectionAssetMapper collectionAssetMapper;

    @Autowired
    private ThreadPoolProxy threadPoolProxy;

    @Autowired
    private YsSubjectMapper ysSubjectMapper;

    /**
     * 采集用友数据
     *
     * @param year  年
     * @param month 月
     * @return 是否采集成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean collectAssetData(int year, int month) {
        // 插入采集记录状态表
        // 获取当前登录账户
        String userName = HttpUtil.getRequestHeaderInfo(Constants.USER_NAME);
        YsCollectionRecord ysCollectionRecordDto = new YsCollectionRecord();
        ysCollectionRecordDto.setOperPerson(userName);
        ysCollectionRecordDto.setOperTime(LocalDateTime.now());
        ysCollectionRecordDto.setCollectionMonth(year + "-" + month);
        ysCollectionRecordDto.setCollectionState(0);
        ysCollectionRecordDto.setType(1);
        baseMapper.insertCollectionRecord(ysCollectionRecordDto);

        try {
            // 选择月的第一天
            LocalDate startDate = getFirstDay(year, month);
            LocalDate endDate = getLastDay(year, month);
            // 选择月下个月的第一天
            endDate = endDate.plusDays(1);
            List<String> listSplit = Arrays.asList(startDate.toString().split("-"));
            String period = listSplit.get(0) + listSplit.get(1);
            // 从用友获取选择月的所有凭证
            List<YsEtlAccount> ysEtlAccount = collectionAccountMapper.selectAccount(year, startDate, endDate, Integer.valueOf(period));

            // 从用友获取选择月的所有资产明细
            List<YsEtlAssetDetails> ysEtlAssetDetails = collectionAssetMapper.selectAssetDetails(year, month);
            ysEtlAssetDetails.forEach(s -> s.setPeriod(Integer.parseInt(period)));

            // 删除凭证表数据
            baseMapper.deleteEtlAccount(period);
            // 删除资产明细表的数据
            baseMapper.deleteDetail(year, month);

            // 为防止插入字符超过最大数,分批插入
            insertData(YsEtlAccount.class, ysEtlAccount);
            insertData(YsEtlAssetDetails.class, ysEtlAssetDetails);
            // 查询数据，匹配预算科目编码和部门编码插入表YS_ACCOUNT_DETAIL
            insertAccountDetail(period);

            baseMapper.updateCollectionState(1);
        } catch (Exception e) {
            baseMapper.updateCollectionState(2);
            throw new RuntimeException("采集失败");
        }
        return true;
    }

    private void insertAccountDetail(String period) throws Exception {
        baseMapper.deleteAccountDetail(period);
        List<YsAccountDetail> accountList = baseMapper.selectAccountList(period);

        // 将对象转为 JSON 字符串
        String json = JSON.toJSONString(accountList);
        List<YsAccountDetail> accountListNew = JSON.parseArray(json, YsAccountDetail.class);
        // ysEtlAccount  筛选出需要特殊处理的数据
        List<String> special = Arrays.asList("50010216", "51010216", "50010212", "51010212", "5001029910", "5101029910", "51010201", "50010201",
                "50010207", "51010207", "50010214", "51010214", "50010229", "51010229", "5001021301", "5101021301",
                "500102130402", "510102130402", "500102130401", "510102130401", "500102130404", "510102130404", "50010215", "51010215",
                "5001029901", "5101029901", "5001020902", "5101020902", "50010209010", "5101029999", "5001029999", "50010218020402", "500102180201",
                "5001029909", "5101029909", "51010205", "50010205", "50010206", "51010206");

        accountListNew = accountListNew.stream().filter(t -> (!special.contains(t.getAccountCode()))).collect(Collectors.toList());
        insertData(YsAccountDetail.class, accountListNew);
        List<YsAccountDetail> specialDataList = setCode(accountList);
        insertData(YsAccountDetail.class, specialDataList);
    }

    private List<YsAccountDetail> setCode(List<YsAccountDetail> accountList) {
        // 查询预算科目表，将subjectCode作为key，subjectId作为值存为一个map
        List<YsSubjectListVO> ysSubjectList = ysSubjectMapper.selectChildList();
        Map<String, Integer> subjectMap = ysSubjectList.stream().collect(Collectors.toMap(YsSubjectListVO::getSubjectCode, YsSubjectListVO::getId, (key1, key2) -> key2));
        // 先将accountList里面变为空，重新对应预算科目
        accountList.stream().forEach(s -> s.setSubjectId(null));

        List<YsAccountDetail> specialDataList = new ArrayList<>();
        // 1 摘要中不含“版面费” -> 进修培训（国内、国外） ; 摘要中含“版面费” -> 版面费
        List<YsAccountDetail> list1 = accountList.stream().filter(t -> ("50010216".equals(t.getAccountCode()) || "51010216".equals(t.getAccountCode())
                || "50010212".equals(t.getAccountCode()) || "51010212".equals(t.getAccountCode())
        )).collect(Collectors.toList());
        list1.forEach(s -> {
            if (("50010216".equals(s.getAccountCode()) || "51010216".equals(s.getAccountCode()))) {
                if (s.getDescription() != null){
                    if (s.getDescription().contains("版面费")) {
                        s.setSubjectId(subjectMap.get("20020802"));
                    } else {
                        s.setSubjectId(subjectMap.get("20020801"));
                    }
                }else{
                    s.setSubjectId(subjectMap.get("20020801"));
                }
            }
            if (("51010212".equals(s.getAccountCode()) || "50010212".equals(s.getAccountCode()))) {
                if (s.getDescription() != null){
                    if (!s.getDescription().contains("会议")) {
                        s.setSubjectId(subjectMap.get("20020803"));
                    } else {
                        s.setSubjectId(subjectMap.get("20050302"));
                    }
                }else{
                    s.setSubjectId(subjectMap.get("20050302"));
                }
            }
        });
        list1 = list1.stream().distinct().collect(Collectors.toList());

        // 2 摘要中不含摘要“订”->20031201宣传费;摘要中含摘要“订”->20031202报刊杂志费
        List<YsAccountDetail> list2 = accountList.stream().filter(t -> ("5001029910".equals(t.getAccountCode()) || "5101029910".equals(t.getAccountCode())
                || "51010201".equals(t.getAccountCode()) || "50010201".equals(t.getAccountCode())
        )).collect(Collectors.toList());
        list2.forEach(s -> {
            // 5001029910 宣传费
            if ("5001029910".equals(s.getAccountCode()) || "5101029910".equals(s.getAccountCode())) {
                if (s.getDescription() != null) {
                    if (s.getDescription().contains("订")) {
                        s.setSubjectId(subjectMap.get("20031202"));
                    } else {
                        s.setSubjectId(subjectMap.get("20031201"));
                    }
                }else{
                    s.setSubjectId(subjectMap.get("20031201"));
                }
            }
            // 办公费
            if ("51010201".equals(s.getAccountCode()) || "50010201".equals(s.getAccountCode())) {
                if (s.getDescription() != null) {
                    if (s.getDescription().contains("订")) {
                        s.setSubjectId(subjectMap.get("20031202"));
                    } else {
                        s.setSubjectId(subjectMap.get("20030101"));
                    }
                }else{
                    s.setSubjectId(subjectMap.get("20030101"));
                }
            }
        });
        list2 = list2.stream().distinct().collect(Collectors.toList());

        // 3.摘要中不含"快递" ->20031401电话费
        List<YsAccountDetail> list3 = accountList.stream().filter(t -> ("50010207".equals(t.getAccountCode())) || "51010207".equals(t.getAccountCode())).collect(Collectors.toList());
        list3.forEach(s -> {
            if (s.getDescription() != null && !s.getDescription().contains("快递")) {
                s.setSubjectId(subjectMap.get("20031401"));
            }
            if (s.getDescription() != null && !(s.getDescription().contains("通信") || s.getDescription().contains("通讯") || s.getDescription().contains("移动电话")
                    || s.getDescription().contains("话费"))) {
                s.setSubjectId(subjectMap.get("20031301"));
            }
        });
        list3 = list3.stream().distinct().collect(Collectors.toList());

        // 4.房租  or 停车租赁费
        List<YsAccountDetail> list4 = accountList.stream().filter(t -> ("50010214".equals(t.getAccountCode()) || "51010214".equals(t.getAccountCode())
                || "50010229".equals(t.getAccountCode()) || "51010229".equals(t.getAccountCode())
        )).collect(Collectors.toList());
        list4.forEach(s -> {
            if (s.getDescription() != null && !(s.getDescription().contains("车") || s.getDescription().contains("待摊") || s.getDescription().contains("医用气体")
                    || s.getDescription().contains("档案") || s.getDescription().contains("设备")
            )) {
                s.setSubjectId(subjectMap.get("20031501"));
            }
            if (s.getDescription() != null && s.getDescription().contains("车")) {
                s.setSubjectId(subjectMap.get("20031502"));
            }
            if (("50010214".equals(s.getAccountCode()) || "51010214".equals(s.getAccountCode()))
                    && s.getDescription() != null && s.getDescription().contains("设备")) {
                s.setSubjectId(subjectMap.get("20031503"));
            }
        });
        list4 = list4.stream().distinct().collect(Collectors.toList());

        // 6.摘要中不含"待摊"
        List<YsAccountDetail> list6 = accountList.stream().filter(t -> ("5001021301".equals(t.getAccountCode()) || "5101021301".equals(t.getAccountCode())
                || "500102130402".equals(t.getAccountCode()) || "510102130402".equals(t.getAccountCode())
                || "500102130401".equals(t.getAccountCode()) || "510102130401".equals(t.getAccountCode())
                || "500102130404".equals(t.getAccountCode()) || "510102130404".equals(t.getAccountCode())
        )).collect(Collectors.toList());
        list6.forEach(s -> {
            if (("5001021301".equals(s.getAccountCode()) || "5101021301".equals(s.getAccountCode())
                    || "500102130402".equals(s.getAccountCode()) || "510102130402".equals(s.getAccountCode()))
                    && s.getDescription() != null && !s.getDescription().contains("待摊")) {
                s.setSubjectId(subjectMap.get("20040101"));
            }
            if (("500102130401".equals(s.getAccountCode()) || "510102130401".equals(s.getAccountCode()))
                    && s.getDescription() != null && !s.getDescription().contains("待摊")) {
                s.setSubjectId(subjectMap.get("20040301"));
            }
            if (("500102130404".equals(s.getAccountCode()) || "510102130404".equals(s.getAccountCode()))
                    && s.getDescription() != null && !s.getDescription().contains("待摊")) {
                s.setSubjectId(subjectMap.get("20040302"));
            }
        });
        list6 = list6.stream().distinct().collect(Collectors.toList());

        // 7.摘要中含有"学习班"->举办继续教育20050201;摘要中不含有"学习班"->举办学术会议20050101
        List<YsAccountDetail> list7 = accountList.stream().filter(t -> ("50010215".equals(t.getAccountCode()) || "51010215".equals(t.getAccountCode()))).collect(Collectors.toList());
        list7.forEach(s -> {
            if (s.getDescription() != null && s.getDescription().contains("学习班")) {
                s.setSubjectId(subjectMap.get("20050201"));
            } else {
                s.setSubjectId(subjectMap.get("20050101"));
            }
        });
        list7 = list7.stream().distinct().collect(Collectors.toList());


        // 8.'部门非“护理部”、摘要不含“实习生” -> 研究生支出20050501;
        // '部门非“护理部”、摘要含“实习生”->教学支出（教育处）20050601;
        // '部门为“护理部”->教学支出（护理部）20050602
        List<YsAccountDetail> list8 = accountList.stream().filter(t -> ("5001029901".equals(t.getAccountCode()) || "5101029901".equals(t.getAccountCode()))).collect(Collectors.toList());
        list8.forEach(s -> {
            if (!"700410".equals(s.getDeptCode()) && !"400810".equals(s.getDeptCode())) {
                if (s.getDescription() != null && s.getDescription().contains("实习")) {
                    s.setSubjectId(subjectMap.get("20050601"));
                } else {
                    s.setSubjectId(subjectMap.get("20050501"));
                }
            } else {
                s.setSubjectId(subjectMap.get("20050602"));
            }
        });
        list8 = list8.stream().distinct().collect(Collectors.toList());

        // 9.部门为“武装保卫处”或“（浒）保卫处” ->安保服务费20060701;
        // 部门不是“武装保卫处”或“（浒）保卫处” ->物业服务费20060702
        List<YsAccountDetail> list9 = accountList.stream().filter(t -> ("5001020902".equals(t.getAccountCode()) || "5101020902".equals(t.getAccountCode()))).collect(Collectors.toList());
        list9.forEach(s -> {
            if ("4019".equals(s.getDeptCode()) || "700610".equals(s.getDeptCode())) {
                s.setSubjectId(subjectMap.get("20060701"));
            } else {
                s.setSubjectId(subjectMap.get("20060702"));
            }
        });
        list9 = list9.stream().distinct().collect(Collectors.toList());

        // 10.部门为“后勤处”或“（浒）后勤处” ->物业服务费 20060702
        List<YsAccountDetail> list10 = accountList.stream().filter(t -> ("50010209010".equals(t.getAccountCode()))).collect(Collectors.toList());
        list10.forEach(s -> {
            if ("4015".equals(s.getDeptCode()) || "700601".equals(s.getDeptCode())) {
                s.setSubjectId(subjectMap.get("20060702"));
            }
        });
        list10 = list10.stream().distinct().collect(Collectors.toList());

        // 11.摘要中不含“专利费”->其他；摘要中含“专利费” -> 专利费
        List<YsAccountDetail> list11 = accountList.stream().filter(t -> ("5101029999".equals(t.getAccountCode()) || "5001029999".equals(t.getAccountCode()))).collect(Collectors.toList());
        list11.forEach(s -> {
            if ("5101029999".equals(s.getAccountCode()) &&  ("4015".equals(s.getDeptCode()) || "700601".equals(s.getDeptCode()))){
                s.setSubjectId(subjectMap.get("20060702"));
            }else{
                if (s.getDescription() != null && !s.getDescription().contains("专利")) {
                    s.setSubjectId(subjectMap.get("20030701"));
                } else {
                    s.setSubjectId(subjectMap.get("20030702"));
                }
            }
        });
        list11 = list11.stream().distinct().collect(Collectors.toList());

        // 12.”外送外检“科目50010218020402。摘要不含”材料出库“  外送外检是不含材料出库，材料费用是含材料出库
        List<YsAccountDetail> list12 = accountList.stream().filter(t -> ("50010218020402".equals(t.getAccountCode())
        )).collect(Collectors.toList());
        list12.forEach(s -> {
            if(s.getDescription() != null && !s.getDescription().contains("材料出库")){
                s.setSubjectId(subjectMap.get("20010201"));
            }else{
                s.setSubjectId(subjectMap.get("20010101"));
            }
        });
        list12 = list12.stream().distinct().collect(Collectors.toList());

        // 13.”血费“科目500102180201。摘要不含”材料出库“
        List<YsAccountDetail> list13 = accountList.stream().filter(t -> ("500102180201".equals(t.getAccountCode())
        )).collect(Collectors.toList());
        list13.forEach(s -> {
            if ( s.getDescription() != null && !s.getDescription().contains("材料出库")) {
                s.setSubjectId(subjectMap.get("20010301"));
            } else {
                s.setSubjectId(subjectMap.get("20010101"));
            }
        });
        list13 = list13.stream().distinct().collect(Collectors.toList());

        // 14. 水费、电费、蒸汽燃气费，摘要不含“预提"
        List<YsAccountDetail> list14 = accountList.stream().filter(t -> (("5001029909".equals(t.getAccountCode()) || "5101029909".equals(t.getAccountCode()) || "50010205".equals(t.getAccountCode()) || "51010205".equals(t.getAccountCode()) || "50010206".equals(t.getAccountCode()) || "51010206".equals(t.getAccountCode()))
                && (t.getDescription() != null && !t.getDescription().contains("预提"))
        )).collect(Collectors.toList());
        list14.forEach(s -> {
            if (("5001029909".equals(s.getAccountCode()) || "5101029909".equals(s.getAccountCode()))) {
                s.setSubjectId(subjectMap.get("20060201"));
            }
            if ("50010205".equals(s.getAccountCode()) || "51010205".equals(s.getAccountCode())) {
                s.setSubjectId(subjectMap.get("20060301"));
            }
            if ("50010206".equals(s.getAccountCode()) || "51010206".equals(s.getAccountCode())) {
                s.setSubjectId(subjectMap.get("20060501"));
            }
        });
        list14 = list14.stream().distinct().collect(Collectors.toList());


        specialDataList.addAll(list1);
        specialDataList.addAll(list2);
        specialDataList.addAll(list3);
        specialDataList.addAll(list4);
        specialDataList.addAll(list6);
        specialDataList.addAll(list7);
        specialDataList.addAll(list8);
        specialDataList.addAll(list9);
        specialDataList.addAll(list10);
        specialDataList.addAll(list11);
        specialDataList.addAll(list12);
        specialDataList.addAll(list13);
        specialDataList.addAll(list14);
        return specialDataList;
    }

    private <T> void insertData(Class<T> clazz, List<T> account) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class<? extends YsEtlAccountMapper> aClass1 = baseMapper.getClass();
        int total = account.size();
        if (total > 0) {
            int fromIndex = 0;
            List<T> insertList = new ArrayList<>();
            for (int i = 0; i < account.size(); i++) {
                T item = account.get(i);
                fromIndex++;
                insertList.add(item);
                if (fromIndex % 50 == 0 && fromIndex <= total) {
                    if (clazz.equals(YsEtlAccount.class)) {
                        aClass1.getMethod("insertBatch", List.class).invoke(baseMapper, insertList);
                        insertList = new ArrayList<>();
                    }
                    if (clazz.equals(YsEtlAssetDetails.class)) {
                        aClass1.getMethod("insertDetailsBatch", List.class).invoke(baseMapper, insertList);
                        insertList = new ArrayList<>();
                    }
                    if (clazz.equals(YsAccountDetail.class)) {
                        aClass1.getMethod("insertAccountDetailsBatch", List.class).invoke(baseMapper, insertList);
                        insertList = new ArrayList<>();
                    }
                }
            }
            if (CollectionUtils.isNotEmpty(insertList)) {
                if (clazz.equals(YsEtlAccount.class)) {
                    aClass1.getMethod("insertBatch", List.class).invoke(baseMapper, insertList);
                }
                if (clazz.equals(YsEtlAssetDetails.class)) {
                    aClass1.getMethod("insertDetailsBatch", List.class).invoke(baseMapper, insertList);
                }
                if (clazz.equals(YsAccountDetail.class)) {
                    aClass1.getMethod("insertAccountDetailsBatch", List.class).invoke(baseMapper, insertList);
                }
            }
        }
    }

    /**
     * 采集用友科目数据
     *
     * @param year 年
     * @return 是否采集成功
     */
    @Override
    public Boolean collectSubjectData(int year) {
        try {
            // 重复采集的时候删除之前数据
            baseMapper.deleteByYear(year);
            List<YsEtlCollectionSubject> ysEtlCollectionSubjects = collectionAccountMapper.collectSubjectData(year);
            int total = ysEtlCollectionSubjects.size();
            if (total > 0) {
                int fromIndex = 0;
                List<YsEtlCollectionSubject> insertList = new ArrayList<>();
                for (YsEtlCollectionSubject item : ysEtlCollectionSubjects) {
                    fromIndex++;
                    insertList.add(item);
                    if (fromIndex % 20 == 0 && fromIndex <= total) {
                        baseMapper.insertSubjectBatch(insertList);
                        insertList = new ArrayList<>();
                    }
                }
                if (CollectionUtils.isNotEmpty(insertList)) {
                    baseMapper.insertSubjectBatch(insertList);
                }
            }
        } catch (RuntimeException e) {
            throw new RuntimeException("采集失败");
        }
        return true;
    }

    /**
     * 获取采集记录列表
     *
     * @param dto 分页参数
     * @return result
     */
    @Override
    public PageInfo<YsCollectionRecord> getYsCollectionRecordList(YsCollectionRecordDTO dto) {
        List<YsCollectionRecord> recordList = baseMapper.getYsCollectionRecordList();
        return PageHelperTool.excutePageInfo(recordList, dto.getPageNum(), dto.getPageSize());
    }

    @Override
    public List<YsDeptVO> getYyDept() {
        List<YsDeptVO> yyDept = collectionAccountMapper.getYyDept();
        return yyDept;
    }

}
